home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9203.ZIP / DFLAT.392 < prev    next >
Text File  |  1992-01-24  |  16KB  |  550 lines

  1. _C PROGRAMMING COLUMN_
  2. by Al Stevens
  3.  
  4. [LISTING ONE]
  5.  
  6. /* ------------- listbox.c ------------ */
  7.  
  8. #include "dflat.h"
  9.  
  10. #ifdef INCLUDE_EXTENDEDSELECTIONS
  11. static int ExtendSelections(WINDOW, int, int);
  12. static void TestExtended(WINDOW, PARAM);
  13. static void ClearAllSelections(WINDOW);
  14. static void SetSelection(WINDOW, int);
  15. static void FlipSelection(WINDOW, int);
  16. static void ClearSelection(WINDOW, int);
  17. #else
  18. #define TestExtended(w,p) /**/
  19. #endif
  20. static void near ChangeSelection(WINDOW, int, int);
  21. static void near WriteSelection(WINDOW, int, int, RECT *);
  22. static int near SelectionInWindow(WINDOW, int);
  23.  
  24. static int py = -1;    /* the previous y mouse coordinate */
  25.  
  26. #ifdef INCLUDE_EXTENDEDSELECTIONS
  27. /* --------- SHIFT_F8 Key ------------ */
  28. static void AddModeKey(WINDOW wnd)
  29. {
  30.     if (isMultiLine(wnd))    {
  31.         wnd->AddMode ^= TRUE;
  32.         SendMessage(GetParent(wnd), ADDSTATUS,
  33.             wnd->AddMode ? ((PARAM) "Add Mode") : 0, 0);
  34.     }
  35. }
  36. #endif
  37.  
  38. /* --------- UP (Up Arrow) Key ------------ */
  39. static void UpKey(WINDOW wnd, PARAM p2)
  40. {
  41.     if (wnd->selection > 0)    {
  42.         if (wnd->selection == wnd->wtop)    {
  43.             BaseWndProc(LISTBOX, wnd, KEYBOARD, UP, p2);
  44.             PostMessage(wnd, LB_SELECTION, wnd->selection-1,
  45.                 isMultiLine(wnd) ? p2 : FALSE);
  46.         }
  47.         else    {
  48.             int newsel = wnd->selection-1;
  49.             if (wnd->wlines == ClientHeight(wnd))
  50.                 while (*TextLine(wnd, newsel) == LINE)
  51.                     --newsel;
  52.             PostMessage(wnd, LB_SELECTION, newsel,
  53. #ifdef INCLUDE_EXTENDEDSELECTIONS
  54.                 isMultiLine(wnd) ? p2 :
  55. #endif
  56.                 FALSE);
  57.         }
  58.     }
  59. }
  60.  
  61. /* --------- DN (Down Arrow) Key ------------ */
  62. static void DnKey(WINDOW wnd, PARAM p2)
  63. {
  64.     if (wnd->selection < wnd->wlines-1)    {
  65.         if (wnd->selection == wnd->wtop+ClientHeight(wnd)-1)  {
  66.             BaseWndProc(LISTBOX, wnd, KEYBOARD, DN, p2);
  67.             PostMessage(wnd, LB_SELECTION, wnd->selection+1,
  68.                 isMultiLine(wnd) ? p2 : FALSE);
  69.         }
  70.         else    {
  71.             int newsel = wnd->selection+1;
  72.             if (wnd->wlines == ClientHeight(wnd))
  73.                 while (*TextLine(wnd, newsel) == LINE)
  74.                     newsel++;
  75.             PostMessage(wnd, LB_SELECTION, newsel,
  76. #ifdef INCLUDE_EXTENDEDSELECTIONS
  77.                 isMultiLine(wnd) ? p2 :
  78. #endif
  79.                 FALSE);
  80.         }
  81.     }
  82. }
  83.  
  84. /* --------- HOME and PGUP Keys ------------ */
  85. static void HomePgUpKey(WINDOW wnd, PARAM p1, PARAM p2)
  86. {
  87.     BaseWndProc(LISTBOX, wnd, KEYBOARD, p1, p2);
  88.     PostMessage(wnd, LB_SELECTION, wnd->wtop,
  89. #ifdef INCLUDE_EXTENDEDSELECTIONS
  90.         isMultiLine(wnd) ? p2 :
  91. #endif
  92.         FALSE);
  93. }
  94.  
  95. /* --------- END and PGDN Keys ------------ */
  96. static void EndPgDnKey(WINDOW wnd, PARAM p1, PARAM p2)
  97. {
  98.     int bot;
  99.     BaseWndProc(LISTBOX, wnd, KEYBOARD, p1, p2);
  100.     bot = wnd->wtop+ClientHeight(wnd)-1;
  101.     if (bot > wnd->wlines-1)
  102.         bot = wnd->wlines-1;
  103.     PostMessage(wnd, LB_SELECTION, bot,
  104. #ifdef INCLUDE_EXTENDEDSELECTIONS
  105.         isMultiLine(wnd) ? p2 :
  106. #endif
  107.         FALSE);
  108. }
  109.  
  110. #ifdef INCLUDE_EXTENDEDSELECTIONS
  111. /* --------- Space Bar Key ------------ */
  112. static void SpacebarKey(WINDOW wnd, PARAM p2)
  113. {
  114.     if (isMultiLine(wnd))    {
  115.         int sel = SendMessage(wnd, LB_CURRENTSELECTION, 0, 0);
  116.         if (sel != -1)    {
  117.             if (wnd->AddMode)
  118.                 FlipSelection(wnd, sel);
  119.             if (ItemSelected(wnd, sel))    {
  120.                 if (!((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))
  121.                     wnd->AnchorPoint = sel;
  122.                 ExtendSelections(wnd, sel, (int) p2);
  123.             }
  124.             else
  125.                 wnd->AnchorPoint = -1;
  126.             SendMessage(wnd, PAINT, 0, 0);
  127.         }
  128.     }
  129. }
  130. #endif
  131.  
  132. /* --------- Enter ('\r') Key ------------ */
  133. static void EnterKey(WINDOW wnd)
  134. {
  135.     if (wnd->selection != -1)    {
  136.         SendMessage(wnd, LB_SELECTION, wnd->selection, TRUE);
  137.         SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  138.     }
  139. }
  140.  
  141. /* --------- All Other Key Presses ------------ */
  142. static void KeyPress(WINDOW wnd, PARAM p1, PARAM p2)
  143. {
  144.     int sel = wnd->selection+1;
  145.     while (sel < wnd->wlines)    {
  146.         char *cp = TextLine(wnd, sel);
  147.         if (cp == NULL)
  148.             break;
  149. #ifdef INCLUDE_EXTENDEDSELECTIONS
  150.         if (isMultiLine(wnd))
  151.             cp++;
  152. #endif
  153.         /* --- special for directory list box --- */
  154.         if (*cp == '[')
  155.             cp++;
  156.         if (tolower(*cp) == (int)p1)    {
  157.             SendMessage(wnd, LB_SELECTION, sel,
  158.                 isMultiLine(wnd) ? p2 : FALSE);
  159.             if (!SelectionInWindow(wnd, sel))    {
  160.                 wnd->wtop = sel-ClientHeight(wnd)+1;
  161.                 SendMessage(wnd, PAINT, 0, 0);
  162.             }
  163.             break;
  164.         }
  165.         sel++;
  166.     }
  167. }
  168.  
  169. /* --------- KEYBOARD Message ------------ */
  170. static int KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  171. {
  172.     switch ((int) p1)    {
  173. #ifdef INCLUDE_EXTENDEDSELECTIONS
  174.         case SHIFT_F8:
  175.             AddModeKey(wnd);
  176.             return TRUE;
  177. #endif
  178.         case UP:
  179.             TestExtended(wnd, p2);
  180.             UpKey(wnd, p2);
  181.             return TRUE;
  182.         case DN:
  183.             TestExtended(wnd, p2);
  184.             DnKey(wnd, p2);
  185.             return TRUE;
  186.         case PGUP:
  187.         case HOME:
  188.             TestExtended(wnd, p2);
  189.             HomePgUpKey(wnd, p1, p2);
  190.             return TRUE;
  191.         case PGDN:
  192.         case END:
  193.             TestExtended(wnd, p2);
  194.             EndPgDnKey(wnd, p1, p2);
  195.             return TRUE;
  196. #ifdef INCLUDE_EXTENDEDSELECTIONS
  197.         case ' ':
  198.             SpacebarKey(wnd, p2);
  199.             break;
  200. #endif
  201.         case '\r':
  202.             EnterKey(wnd);
  203.             return TRUE;
  204.         default:
  205.             KeyPress(wnd, p1, p2);
  206.             break;
  207.     }
  208.     return FALSE;
  209. }
  210.  
  211. /* ------- LEFT_BUTTON Message -------- */
  212. static int LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  213. {
  214.     int my = (int) p2 - GetTop(wnd);
  215.     if (my >= wnd->wlines-wnd->wtop)
  216.         my = wnd->wlines - wnd->wtop;
  217.  
  218.     if (WindowMoving || WindowSizing)
  219.         return FALSE;
  220.     if (!InsideRect(p1, p2, ClientRect(wnd)))
  221.         return FALSE;
  222.     if (wnd->wlines && my != py)    {
  223.         int sel = wnd->wtop+my-1;
  224. #ifdef INCLUDE_EXTENDEDSELECTIONS
  225.         int sh = getshift();
  226.         if (!(sh & (LEFTSHIFT | RIGHTSHIFT)))    {
  227.             if (!(sh & CTRLKEY))
  228.                 ClearAllSelections(wnd);
  229.             wnd->AnchorPoint = sel;
  230.             SendMessage(wnd, PAINT, 0, 0);
  231.         }
  232. #endif
  233.         SendMessage(wnd, LB_SELECTION, sel, TRUE);
  234.         py = my;
  235.     }
  236.     return TRUE;
  237. }
  238.  
  239. /* ------------- DOUBLE_CLICK Message ------------ */
  240. static int DoubleClickMsg(WINDOW wnd, PARAM p1, PARAM p2)
  241. {
  242.     if (WindowMoving || WindowSizing)
  243.         return FALSE;
  244.     if (wnd->wlines)    {
  245.         RECT rc = ClientRect(wnd);
  246.         BaseWndProc(LISTBOX, wnd, DOUBLE_CLICK, p1, p2);
  247.         if (InsideRect(p1, p2, rc))
  248.             SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  249.     }
  250.     return TRUE;
  251. }
  252.  
  253. /* ------------ ADDTEXT Message -------------- */
  254. static int AddTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  255. {
  256.     int rtn = BaseWndProc(LISTBOX, wnd, ADDTEXT, p1, p2);
  257.     if (wnd->selection == -1)
  258.         SendMessage(wnd, LB_SETSELECTION, 0, 0);
  259. #ifdef INCLUDE_EXTENDEDSELECTIONS
  260.     if (*(char *)p1 == LISTSELECTOR)
  261.         wnd->SelectCount++;
  262. #endif
  263.     return rtn;
  264. }
  265.  
  266. /* --------- GETTEXT Message ------------ */
  267. static void GetTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  268. {
  269.     if ((int)p2 != -1)    {
  270.         char *cp1 = (char *)p1;
  271.         char *cp2 = TextLine(wnd, (int)p2);
  272.         while (cp2 && *cp2 && *cp2 != '\n')
  273.             *cp1++ = *cp2++;
  274.         *cp1 = '\0';
  275.     }
  276. }
  277.  
  278. /* --------- LISTBOX Window Processing Module ------------ */
  279. int ListBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  280. {
  281.     switch (msg)    {
  282.         case CREATE_WINDOW:
  283.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  284.             wnd->selection = -1;
  285. #ifdef INCLUDE_EXTENDEDSELECTIONS
  286.             wnd->AnchorPoint = -1;
  287. #endif
  288.             return TRUE;
  289.         case KEYBOARD:
  290.             if (WindowMoving || WindowSizing)
  291.                 break;
  292.             if (KeyboardMsg(wnd, p1, p2))
  293.                 return TRUE;
  294.             break;
  295.         case LEFT_BUTTON:
  296.             if (LeftButtonMsg(wnd, p1, p2) == TRUE)
  297.                 return TRUE;
  298.             break;
  299.         case DOUBLE_CLICK:
  300.             if (DoubleClickMsg(wnd, p1, p2))
  301.                 return TRUE;
  302.             break;
  303.         case BUTTON_RELEASED:
  304.             py = -1;
  305.             return TRUE;
  306.         case ADDTEXT:
  307.             return AddTextMsg(wnd, p1, p2);
  308.         case LB_GETTEXT:
  309.             GetTextMsg(wnd, p1, p2);
  310.             return TRUE;
  311.         case CLEARTEXT:
  312.             wnd->selection = -1;
  313. #ifdef INCLUDE_EXTENDEDSELECTIONS
  314.             wnd->AnchorPoint = -1;
  315. #endif
  316.             wnd->SelectCount = 0;
  317.             break;
  318.         case PAINT:
  319.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  320.             WriteSelection(wnd, wnd->selection, TRUE, (RECT *)p1);
  321.             return TRUE;
  322.         case SCROLL:
  323.         case HORIZSCROLL:
  324.         case SCROLLPAGE:
  325.         case HORIZPAGE:
  326.         case SCROLLDOC:
  327.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  328.             WriteSelection(wnd,wnd->selection,TRUE,NULL);
  329.             return TRUE;
  330.         case LB_CHOOSE:
  331.             SendMessage(GetParent(wnd), LB_CHOOSE, p1, p2);
  332.             return TRUE;
  333.         case LB_SELECTION:
  334.             ChangeSelection(wnd, (int) p1, (int) p2);
  335.             SendMessage(GetParent(wnd), LB_SELECTION,
  336.                 wnd->selection, 0);
  337.             return TRUE;
  338.         case LB_CURRENTSELECTION:
  339.             return wnd->selection;
  340.         case LB_SETSELECTION:
  341.             ChangeSelection(wnd, (int) p1, 0);
  342.             return TRUE;
  343. #ifdef INCLUDE_EXTENDEDSELECTIONS
  344.         case CLOSE_WINDOW:
  345.             if (isMultiLine(wnd) && wnd->AddMode)    {
  346.                 wnd->AddMode = FALSE;
  347.                 SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
  348.             }
  349.             break;
  350. #endif
  351.         default:
  352.             break;
  353.     }
  354.     return BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  355. }
  356.  
  357. static int near SelectionInWindow(WINDOW wnd, int sel)
  358. {
  359.     return (wnd->wlines && sel >= wnd->wtop &&
  360.             sel < wnd->wtop+ClientHeight(wnd));
  361. }
  362.  
  363. static void near WriteSelection(WINDOW wnd, int sel,
  364.                                     int reverse, RECT *rc)
  365. {
  366.     if (isVisible(wnd))
  367.         if (SelectionInWindow(wnd, sel))
  368.             WriteTextLine(wnd, rc, sel, reverse);
  369. }
  370.  
  371. #ifdef INCLUDE_EXTENDEDSELECTIONS
  372. /* ----- Test for extended selections in the listbox ----- */
  373. static void TestExtended(WINDOW wnd, PARAM p2)
  374. {
  375.     if (isMultiLine(wnd) && !wnd->AddMode &&
  376.             !((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))    {
  377.         if (wnd->SelectCount > 1)    {
  378.             ClearAllSelections(wnd);
  379.             SendMessage(wnd, PAINT, 0, 0);
  380.         }
  381.     }
  382. }
  383.  
  384. /* ----- Clear selections in the listbox ----- */
  385. static void ClearAllSelections(WINDOW wnd)
  386. {
  387.     if (isMultiLine(wnd) && wnd->SelectCount > 0)    {
  388.         int sel;
  389.         for (sel = 0; sel < wnd->wlines; sel++)
  390.             ClearSelection(wnd, sel);
  391.     }
  392. }
  393.  
  394. /* ----- Invert a selection in the listbox ----- */
  395. static void FlipSelection(WINDOW wnd, int sel)
  396. {
  397.     if (isMultiLine(wnd))    {
  398.         if (ItemSelected(wnd, sel))
  399.             ClearSelection(wnd, sel);
  400.         else
  401.             SetSelection(wnd, sel);
  402.     }
  403. }
  404.  
  405. static int ExtendSelections(WINDOW wnd, int sel, int shift)
  406. {    
  407.     if (shift & (LEFTSHIFT | RIGHTSHIFT) &&
  408.                         wnd->AnchorPoint != -1)    {
  409.         int i = sel;
  410.         int j = wnd->AnchorPoint;
  411.         int rtn;
  412.         if (j > i)
  413.             swap(i,j);
  414.         rtn = i - j;
  415.         while (j <= i)
  416.             SetSelection(wnd, j++);
  417.         return rtn;
  418.     }
  419.     return 0;
  420. }
  421.  
  422. static void SetSelection(WINDOW wnd, int sel)
  423. {
  424.     if (isMultiLine(wnd) && !ItemSelected(wnd, sel))    {
  425.         char *lp = TextLine(wnd, sel);
  426.         *lp = LISTSELECTOR;
  427.         wnd->SelectCount++;
  428.     }
  429. }
  430.  
  431. static void ClearSelection(WINDOW wnd, int sel)
  432. {
  433.     if (isMultiLine(wnd) && ItemSelected(wnd, sel))    {
  434.         char *lp = TextLine(wnd, sel);
  435.         *lp = ' ';
  436.         --wnd->SelectCount;
  437.     }
  438. }
  439.  
  440. int ItemSelected(WINDOW wnd, int sel)
  441. {
  442.     if (isMultiLine(wnd) && sel < wnd->wlines)    {
  443.         char *cp = TextLine(wnd, sel);
  444.         return (int)((*cp) & 255) == LISTSELECTOR;
  445.     }
  446.     return FALSE;
  447. }
  448. #endif
  449.  
  450. static void near ChangeSelection(WINDOW wnd,int sel,int shift)
  451. {
  452.     if (sel != wnd->selection)    {
  453. #ifdef INCLUDE_EXTENDEDSELECTIONS
  454.         if (isMultiLine(wnd))        {
  455.             int sels;
  456.             if (!wnd->AddMode)
  457.                 ClearAllSelections(wnd);
  458.             sels = ExtendSelections(wnd, sel, shift);
  459.             if (sels > 1)
  460.                 SendMessage(wnd, PAINT, 0, 0);
  461.             if (sels == 0 && !wnd->AddMode)    {
  462.                 ClearSelection(wnd, wnd->selection);
  463.                 SetSelection(wnd, sel);
  464.                 wnd->AnchorPoint = sel;
  465.             }
  466.         }
  467. #endif
  468.         WriteSelection(wnd, wnd->selection, FALSE, NULL);
  469.         wnd->selection = sel;
  470.         WriteSelection(wnd, sel, TRUE, NULL);
  471.      }
  472. }
  473.  
  474.  
  475. [LISTING TWO]
  476.  
  477. /* ------------ log .c ------------ */
  478.  
  479. #include "dflat.h"
  480.  
  481. #ifdef INCLUDE_LOGGING
  482.  
  483. static char *message[] = {
  484.     #undef DFlatMsg
  485.     #define DFlatMsg(m) " " #m,
  486.     #include "dflatmsg.h"
  487.     NULL
  488. };
  489.  
  490. static FILE *log = NULL;
  491. extern DBOX Log;
  492.  
  493. void LogMessages (WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  494. {
  495.     if (log != NULL && message[msg][0] != ' ')
  496.         fprintf(log,
  497.             "%-20.20s %-12.12s %-20.20s, %5.5ld, %5.5ld\n",
  498.             wnd ? (GetTitle(wnd) ? GetTitle(wnd) : "") : "",
  499.             wnd ? ClassNames[GetClass(wnd)] : "",
  500.             message[msg]+1, p1, p2);
  501. }
  502.  
  503. static int LogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  504. {
  505.     WINDOW cwnd = ControlWindow(&Log, ID_LOGLIST);
  506.     char **mn = message;
  507.     switch (msg)    {
  508.         case INITIATE_DIALOG:
  509.             AddAttribute(cwnd, MULTILINE | VSCROLLBAR);
  510.             while (*mn)    {
  511.                 SendMessage(cwnd, ADDTEXT, (PARAM) (*mn), 0);
  512.                 mn++;
  513.             }
  514.             SendMessage(cwnd, SHOW_WINDOW, 0, 0);
  515.             break;
  516.         case COMMAND:
  517.             if ((int) p1 == ID_OK)    {
  518.                 int item;
  519.                 int tl = GetTextLines(cwnd);
  520.                 for (item = 0; item < tl; item++)
  521.                     if (ItemSelected(cwnd, item))
  522.                         mn[item][0] = LISTSELECTOR;
  523.             }
  524.             break;
  525.         default:
  526.             break;
  527.     }
  528.     return DefaultWndProc(wnd, msg, p1, p2);
  529. }
  530.  
  531. void MessageLog(WINDOW wnd)
  532. {
  533.     if (DialogBox(wnd, &Log, TRUE, LogProc))    {
  534.         if (CheckBoxSetting(&Log, ID_LOGGING))    {
  535.             log = fopen("DFLAT.LOG", "wt");
  536.             SetCommandToggle(&MainMenu, ID_LOG);
  537.         }
  538.         else if (log != NULL)    {
  539.             fclose(log);
  540.             log = NULL;
  541.             ClearCommandToggle(&MainMenu, ID_LOG);
  542.         }
  543.     }
  544. }
  545.  
  546. #endif
  547.  
  548.  
  549.  
  550.